///PHILOTES Source Code.  (C)2012 PhiloLabs
#pragma once

#ifndef __GpuProgramManager_H_
#define __GpuProgramManager_H_

// Precompiler options
#include "OgrePrerequisites.h"
#include "OgreResourceManager.h"
#include "core/exception.h"
#include "OgreGpuProgram.h"
#include "OgreSingleton.h"

namespace Ogre {

	
	
	class _OgreExport GpuProgramManager : public ResourceManager, public Singleton<GpuProgramManager>
	{
	public:

		typedef set<String>::type SyntaxCodes;
		typedef map<String, GpuSharedParametersPtr>::type SharedParametersMap;

		typedef MemoryDataStreamPtr Microcode;
		typedef map<String, Microcode>::type MicrocodeMap;

	protected:

		SharedParametersMap mSharedParametersMap;
		MicrocodeMap mMicrocodeCache;
		bool mSaveMicrocodesToCache;
			
		static String addRenderSystemToName( const String &  name );

        /// Specialised create method with specific parameters
        virtual Resource* createImpl(const String& name, ResourceHandle handle, 
            const String& group, bool isManual, ManualResourceLoader* loader,
            GpuProgramType gptype, const String& syntaxCode) = 0;
	public:
		GpuProgramManager();
		virtual ~GpuProgramManager();

        
		virtual GpuProgramPtr load(const String& name, const String& groupName, 
			const String& filename, GpuProgramType gptype, 
            const String& syntaxCode);

		
		virtual GpuProgramPtr loadFromString(const String& name, const String& groupName,
			const String& code, GpuProgramType gptype,
            const String& syntaxCode);

		
		virtual const SyntaxCodes& getSupportedSyntax(void) const;
		 

        
        virtual bool isSyntaxSupported(const String& syntaxCode) const;
		
		
        virtual GpuProgramParametersSharedPtr createParameters(void);
        
        
		virtual GpuProgramPtr createProgram(const String& name, 
			const String& groupName, const String& filename, 
			GpuProgramType gptype, const String& syntaxCode);

		
		virtual GpuProgramPtr createProgramFromString(const String& name, 
			const String& groupName, const String& code, 
            GpuProgramType gptype, const String& syntaxCode);

        
        virtual ResourcePtr create(const String& name, const String& group, 
            GpuProgramType gptype, const String& syntaxCode, bool isManual = false, 
            ManualResourceLoader* loader = 0);

        
        ResourcePtr getByName(const String& name, bool preferHighLevelPrograms = true);


		
		virtual GpuSharedParametersPtr createSharedParameters(const String& name);

		
		virtual GpuSharedParametersPtr getSharedParameters(const String& name) const;

		
		virtual const SharedParametersMap& getAvailableSharedParameters() const;

        
		const bool getSaveMicrocodesToCache() const;
        
		void setSaveMicrocodesToCache( const bool val );

		const bool canGetCompiledShaderBuffer() const;
        
		virtual bool isMicrocodeAvailableInCache( const String & name ) const;
        
		virtual const Microcode & getMicrocodeFromCache( const String & name ) const;

        
		virtual Microcode createMicrocode( const size_t size ) const;

        
		virtual void addMicrocodeToCache( const String & name, const Microcode & microcode );

        
		virtual void saveMicrocodeCache( DataStreamPtr stream ) const;
        
		virtual void loadMicrocodeCache( DataStreamPtr stream );
		


        
        static GpuProgramManager& getSingleton(void);
        
        static GpuProgramManager* getSingletonPtr(void);
    


	};

	
	
}

#endif
